# -*- coding: utf-8 -*-
"""
文件操作日志模型
@api-version: 1.0.0
// REF: API-NETDISK-005
"""

from datetime import datetime
from enum import Enum
from . import db
from .user import User
from .virtual_file import VirtualFile

class OperationType(Enum):
    """操作类型枚举"""
    UPLOAD = 'upload'           # 上传文件
    DOWNLOAD = 'download'       # 下载文件
    DELETE = 'delete'           # 删除文件
    RENAME = 'rename'           # 重命名
    MOVE = 'move'               # 移动文件
    COPY = 'copy'               # 复制文件
    CREATE_FOLDER = 'create_folder'  # 创建文件夹
    SHARE = 'share'             # 分享文件
    UNSHARE = 'unshare'         # 取消分享
    ACCESS = 'access'           # 访问文件
    PREVIEW = 'preview'         # 预览文件
    EDIT = 'edit'               # 编辑文件
    FAVORITE = 'favorite'       # 收藏文件
    UNFAVORITE = 'unfavorite'   # 取消收藏
    HIDE = 'hide'               # 隐藏文件
    UNHIDE = 'unhide'           # 取消隐藏
    TAG_ADD = 'tag_add'         # 添加标签
    TAG_REMOVE = 'tag_remove'   # 移除标签
    QUOTA_UPDATE = 'quota_update'  # 配额更新
    STORAGE_CLEAN = 'storage_clean'  # 存储清理

class FileOperationLog(db.Model):
    """文件操作日志模型
    
    记录用户的所有文件操作，用于审计和统计分析
    支持操作回溯和用户行为分析
    """
    __tablename__ = 'file_operation_logs'
    
    id = db.Column(db.Integer, primary_key=True, comment='日志ID')
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, comment='操作用户ID')
    file_id = db.Column(db.Integer, db.ForeignKey('virtual_files.id'), comment='关联文件ID')
    operation_type = db.Column(db.Enum(OperationType), nullable=False, comment='操作类型')
    operation_detail = db.Column(db.Text, comment='操作详情（JSON格式）')
    target_path = db.Column(db.String(1000), comment='目标路径')
    source_path = db.Column(db.String(1000), comment='源路径（移动/复制操作）')
    file_size = db.Column(db.BigInteger, comment='文件大小（字节）')
    ip_address = db.Column(db.String(45), comment='操作IP地址')
    user_agent = db.Column(db.String(500), comment='用户代理')
    success = db.Column(db.Boolean, nullable=False, default=True, comment='操作是否成功')
    error_message = db.Column(db.Text, comment='错误信息')
    duration_ms = db.Column(db.Integer, comment='操作耗时（毫秒）')
    created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, comment='操作时间')
    
    # 关联关系
    user = db.relationship('User', backref='operation_logs')
    file = db.relationship('VirtualFile', backref='operation_logs')
    
    # 索引
    __table_args__ = (
        db.Index('idx_logs_user_created', 'user_id', 'created_at'),
        db.Index('idx_logs_operation_created', 'operation_type', 'created_at'),
        db.Index('idx_logs_file_operation', 'file_id', 'operation_type'),
        db.Index('idx_logs_success_created', 'success', 'created_at'),
    )
    
    def __init__(self, user_id, operation_type, **kwargs):
        self.user_id = user_id
        self.operation_type = operation_type
        
        # 设置可选参数
        for key, value in kwargs.items():
            if hasattr(self, key):
                setattr(self, key, value)
    
    @staticmethod
    def log_operation(user_id, operation_type, **kwargs):
        """记录操作日志
        
        Args:
            user_id: 用户ID
            operation_type: 操作类型
            **kwargs: 其他参数（file_id, target_path, source_path等）
        """
        try:
            log = FileOperationLog(
                user_id=user_id,
                operation_type=operation_type,
                **kwargs
            )
            db.session.add(log)
            db.session.commit()
            return log
        except Exception as e:
            db.session.rollback()
            # 记录操作失败，静默处理
            return None
    
    @staticmethod
    def log_upload(user_id, file_id, file_size, target_path, **kwargs):
        """记录文件上传"""
        return FileOperationLog.log_operation(
            user_id=user_id,
            operation_type=OperationType.UPLOAD,
            file_id=file_id,
            file_size=file_size,
            target_path=target_path,
            **kwargs
        )
    
    @staticmethod
    def log_download(user_id, file_id, file_size, target_path, **kwargs):
        """记录文件下载"""
        return FileOperationLog.log_operation(
            user_id=user_id,
            operation_type=OperationType.DOWNLOAD,
            file_id=file_id,
            file_size=file_size,
            target_path=target_path,
            **kwargs
        )
    
    @staticmethod
    def log_delete(user_id, file_id, target_path, **kwargs):
        """记录文件删除"""
        return FileOperationLog.log_operation(
            user_id=user_id,
            operation_type=OperationType.DELETE,
            file_id=file_id,
            target_path=target_path,
            **kwargs
        )
    
    @staticmethod
    def log_move(user_id, file_id, source_path, target_path, **kwargs):
        """记录文件移动"""
        return FileOperationLog.log_operation(
            user_id=user_id,
            operation_type=OperationType.MOVE,
            file_id=file_id,
            source_path=source_path,
            target_path=target_path,
            **kwargs
        )
    
    @staticmethod
    def log_copy(user_id, file_id, source_path, target_path, **kwargs):
        """记录文件复制"""
        return FileOperationLog.log_operation(
            user_id=user_id,
            operation_type=OperationType.COPY,
            file_id=file_id,
            source_path=source_path,
            target_path=target_path,
            **kwargs
        )
    
    @staticmethod
    def log_share(user_id, file_id, target_path, **kwargs):
        """记录文件分享"""
        return FileOperationLog.log_operation(
            user_id=user_id,
            operation_type=OperationType.SHARE,
            file_id=file_id,
            target_path=target_path,
            **kwargs
        )
    
    def get_operation_display_name(self):
        """获取操作类型的显示名称"""
        operation_names = {
            OperationType.UPLOAD: '上传文件',
            OperationType.DOWNLOAD: '下载文件',
            OperationType.DELETE: '删除文件',
            OperationType.RENAME: '重命名',
            OperationType.MOVE: '移动文件',
            OperationType.COPY: '复制文件',
            OperationType.CREATE_FOLDER: '创建文件夹',
            OperationType.SHARE: '分享文件',
            OperationType.UNSHARE: '取消分享',
            OperationType.ACCESS: '访问文件',
            OperationType.PREVIEW: '预览文件',
            OperationType.EDIT: '编辑文件',
            OperationType.FAVORITE: '收藏文件',
            OperationType.UNFAVORITE: '取消收藏',
            OperationType.HIDE: '隐藏文件',
            OperationType.UNHIDE: '取消隐藏',
            OperationType.TAG_ADD: '添加标签',
            OperationType.TAG_REMOVE: '移除标签',
            OperationType.QUOTA_UPDATE: '配额更新',
            OperationType.STORAGE_CLEAN: '存储清理'
        }
        return operation_names.get(self.operation_type, '未知操作')
    
    def get_formatted_file_size(self):
        """获取格式化的文件大小"""
        if not self.file_size:
            return None
        
        size = self.file_size
        for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
            if size < 1024.0:
                return f"{size:.1f} {unit}"
            size /= 1024.0
        return f"{size:.1f} PB"
    
    def get_formatted_duration(self):
        """获取格式化的操作耗时"""
        if not self.duration_ms:
            return None
        
        if self.duration_ms < 1000:
            return f"{self.duration_ms}ms"
        elif self.duration_ms < 60000:
            return f"{self.duration_ms / 1000:.1f}s"
        else:
            minutes = self.duration_ms // 60000
            seconds = (self.duration_ms % 60000) / 1000
            return f"{minutes}m {seconds:.1f}s"
    
    @staticmethod
    def get_user_operation_stats(user_id, days=30):
        """获取用户操作统计"""
        from sqlalchemy import func
        from datetime import timedelta
        
        start_date = datetime.utcnow() - timedelta(days=days)
        
        # 按操作类型统计
        operation_stats = db.session.query(
            FileOperationLog.operation_type,
            func.count(FileOperationLog.id).label('count'),
            func.sum(func.coalesce(FileOperationLog.file_size, 0)).label('total_size')
        ).filter(
            FileOperationLog.user_id == user_id,
            FileOperationLog.created_at >= start_date,
            FileOperationLog.success == True
        ).group_by(FileOperationLog.operation_type).all()
        
        # 按日期统计
        daily_stats = db.session.query(
            func.date(FileOperationLog.created_at).label('date'),
            func.count(FileOperationLog.id).label('count')
        ).filter(
            FileOperationLog.user_id == user_id,
            FileOperationLog.created_at >= start_date
        ).group_by(func.date(FileOperationLog.created_at)).all()
        
        return {
            'operation_stats': [{
                'operation_type': stat.operation_type.value,
                'count': stat.count,
                'total_size': stat.total_size
            } for stat in operation_stats],
            'daily_stats': [{
                'date': stat.date.isoformat(),
                'count': stat.count
            } for stat in daily_stats]
        }
    
    @staticmethod
    def get_system_operation_stats(days=30):
        """获取系统操作统计"""
        from sqlalchemy import func
        from datetime import timedelta
        
        start_date = datetime.utcnow() - timedelta(days=days)
        
        # 总体统计
        total_stats = db.session.query(
            func.count(FileOperationLog.id).label('total_operations'),
            func.count(func.distinct(FileOperationLog.user_id)).label('active_users'),
            func.sum(func.coalesce(FileOperationLog.file_size, 0)).label('total_data_transferred')
        ).filter(
            FileOperationLog.created_at >= start_date,
            FileOperationLog.success == True
        ).first()
        
        # 按操作类型统计
        operation_stats = db.session.query(
            FileOperationLog.operation_type,
            func.count(FileOperationLog.id).label('count')
        ).filter(
            FileOperationLog.created_at >= start_date
        ).group_by(FileOperationLog.operation_type).all()
        
        # 错误统计
        error_stats = db.session.query(
            func.count(FileOperationLog.id).label('error_count')
        ).filter(
            FileOperationLog.created_at >= start_date,
            FileOperationLog.success == False
        ).first()
        
        return {
            'total_operations': total_stats.total_operations,
            'active_users': total_stats.active_users,
            'total_data_transferred': total_stats.total_data_transferred,
            'error_count': error_stats.error_count,
            'operation_breakdown': [{
                'operation_type': stat.operation_type.value,
                'count': stat.count
            } for stat in operation_stats]
        }
    
    @staticmethod
    def get_recent_logs(user_id=None, limit=50):
        """获取最近的操作日志"""
        query = FileOperationLog.query
        
        if user_id:
            query = query.filter(FileOperationLog.user_id == user_id)
        
        return query.order_by(FileOperationLog.created_at.desc()).limit(limit).all()
    
    @staticmethod
    def cleanup_old_logs(days=90):
        """清理旧的操作日志"""
        from datetime import timedelta
        
        cutoff_date = datetime.utcnow() - timedelta(days=days)
        
        deleted_count = db.session.query(FileOperationLog).filter(
            FileOperationLog.created_at < cutoff_date
        ).delete()
        
        db.session.commit()
        return deleted_count
    
    def to_dict(self, include_user_info=False, include_file_info=False):
        """转换为字典格式"""
        data = {
            'id': self.id,
            'userId': self.user_id,
            'fileId': self.file_id,
            'operationType': self.operation_type.value,
            'operationDisplayName': self.get_operation_display_name(),
            'operationDetail': self.operation_detail,
            'targetPath': self.target_path,
            'sourcePath': self.source_path,
            'fileSize': self.file_size,
            'formattedFileSize': self.get_formatted_file_size(),
            'ipAddress': self.ip_address,
            'userAgent': self.user_agent,
            'success': self.success,
            'errorMessage': self.error_message,
            'durationMs': self.duration_ms,
            'formattedDuration': self.get_formatted_duration(),
            'createdAt': self.created_at.isoformat() if self.created_at else None
        }
        
        # 包含用户信息
        if include_user_info and self.user:
            data.update({
                'username': self.user.username,
                'nickname': self.user.nickname
            })
        
        # 包含文件信息
        if include_file_info and self.file:
            data.update({
                'fileName': self.file.name,
                'isFolder': self.file.is_folder
            })
        
        return data
    
    def __repr__(self):
        return f'<FileOperationLog user:{self.user_id} op:{self.operation_type.value} success:{self.success}>'